package com.tigear.tihome;

import cm.heclouds.onenet.iot.api.entity.application.device.CallServiceResponse;
import cm.heclouds.onenet.iot.api.entity.application.device.QueryDeviceDetailResponse;
import cm.heclouds.onenet.iot.api.entity.enums.Status;
import cm.heclouds.onenet.iot.api.exception.IotClientException;
import cm.heclouds.onenet.iot.api.exception.IotServerException;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tigear.api.DeviceManagerApi;
import com.tigear.api.DevicePropertyApi;
import com.tigear.api.DeviceServiceApi;
import com.tigear.api.OneNetIotClient;
import com.tigear.tihome.domain.FamilyNumber;
import com.tigear.tihome.domain.FunctionKey;
import com.tigear.tihome.domain.SubDevice;
import com.tigear.tihome.domain.WeekTimerTask;

import java.util.*;

/**
 * TiHome 钛极智能呼叫网关平台接口封装
 * 方便用户将TiHome产品快速集成到自己的平台中， 将常用接口进行了封装， 您也可参考相关代码增加未封装功能
 */
public class TiHome {

    OneNetIotClient oneNetIotClient ;
    DeviceManagerApi deviceManagerApi;
    DevicePropertyApi devicePropertyApi;
    DeviceServiceApi deviceServiceApi;

    String productId = "";
    String deviceName = "";

    /**
     * 初始化
     * @param userId    OneNET平台 userId
     * @param accessKey OneNET平台 access key
     * @param productId 产品ID  “5POpr2bk2g”
     * @param deviceName  设备名称
     */
    public  TiHome(String userId, String accessKey, String productId, String deviceName){
        init(userId, accessKey);

        this.productId = productId;
        this.deviceName = deviceName;
    }

    void init(String userId, String accessKey){

        oneNetIotClient = new OneNetIotClient();
        oneNetIotClient.initClient(userId, accessKey);

        deviceManagerApi = new DeviceManagerApi(oneNetIotClient);
        devicePropertyApi = new DevicePropertyApi(oneNetIotClient);
        deviceServiceApi = new DeviceServiceApi(oneNetIotClient);
    }

    /**
     * 设置设备名称
     * @param deviceName
     */
    public void setDeviceName(String deviceName) {
        this.deviceName = deviceName;
    }

    /**
     * 获取设备状态
     * @return 设备状态
     * @throws IotServerException
     * @throws IotClientException
     */
    public Status getDeviceStatus() throws IotServerException, IotClientException {
        QueryDeviceDetailResponse response =  this.deviceManagerApi.queryDeviceDetail(this.productId, this.deviceName);
        return response.getStatus();
    }

    /**
     * 将设备加入到分组
     * @param groupId  分组ID
     * @throws IotServerException
     * @throws IotClientException
     */
    public  void addToGroup(String groupId) throws IotServerException, IotClientException {
        deviceManagerApi.addGroupDevice(groupId, productId, Collections.singletonList(deviceName));
    }

    /**
     * 从分组中删除设备
     * @param groupId 分组ID
     * @throws IotServerException
     * @throws IotClientException
     */
    public void removeFromGroup(String groupId) throws IotServerException, IotClientException {
        deviceManagerApi.removeGroupDevice(groupId, productId, Collections.singletonList(deviceName));
    }

    /**
     * 设置属性值
     * @param propertyName  属性名称
     * @param propertyValue  属性值
     * @throws IotServerException
     * @throws IotClientException
     */
    public void setPropertyValue(String propertyName, Object propertyValue) throws IotServerException, IotClientException {
        devicePropertyApi.setDeviceProperty(productId, deviceName, propertyName, propertyValue);
    }

    /**
     * 设置属性期望值
     * @param propertyName 属性名称
     * @param propertyValue 属性值
     * @throws IotServerException
     * @throws IotClientException
     */
    public void setDesiredPropertyValue(String propertyName, Object propertyValue) throws IotServerException, IotClientException {
        devicePropertyApi.setDeviceDesiredProperty(productId, deviceName, propertyName, propertyValue);
    }

    /**
     * 获取属性值
     * @param propertyName   属性名称
     * @return  属性值
     * @throws IotServerException
     * @throws IotClientException
     */
    public Object getPropertyValue(String propertyName) throws IotServerException, IotClientException {
        HashMap<String, Object> propertyValues =  devicePropertyApi.queryDevicePropertyValues(this.productId, deviceName, new String[]{propertyName});
        return propertyValues.get(propertyName);
    }

    /**
     * 调用服务
     * @param serviceName  服务名称
     * @param serviceParams 服务参数
     * @return  请求ID
     * @throws IotServerException
     * @throws IotClientException
     */
    public CallServiceResponse callService(String serviceName, Map<String, Object> serviceParams) throws IotServerException, IotClientException {
        CallServiceResponse result = deviceServiceApi.callService(productId, deviceName, serviceName, serviceParams);
        return result;
    }

    /**
     * 重启设备
     * @throws IotServerException
     * @throws IotClientException
     */
    public  void reboot() throws IotServerException, IotClientException {
        HashMap<String, Object> param = new HashMap<>();
        param.put("cmd", 0);

        this.callService("reboot", param);
    }

    /**
     * 远程呼叫
     * @param phone   电话号码， 如果为空字符串，将拔打紧急联系人电话
     * @param text   语音提示， 拔打之前的语音提示
     * @return
     * @throws IotServerException
     * @throws IotClientException
     */
    public String remoteCall(String phone, String text) throws IotServerException, IotClientException {
        HashMap<String, Object> param = new HashMap<>();
        param.put("phone_number", phone);
        param.put("text", text);

        CallServiceResponse response =  this.callService("remote_call", param);
        return response.getRequestId();
    }

    /**
     * 设置紧急联系人
     * @param phoneNumbers   紧急联系人电话
     * @throws IotServerException
     * @throws IotClientException
     */
    public void setUrgentContacts(List<String> phoneNumbers) throws IotServerException, IotClientException {
        String contacts  = "";

        for(int i = 0 ;i  < phoneNumbers.size() ; i ++) {
            contacts += phoneNumbers.get(i);
            if(i < phoneNumbers.size() -1) {
                contacts += ",";
            }
        }

        this.setPropertyValue("emergency_contact", contacts);
    }

    /**
     * 获取紧急联系人
     * @return 紧急联系人列表
     * @throws IotServerException
     * @throws IotClientException
     */
    public List<String> getUrgentContacts()throws IotServerException, IotClientException {
        String result = (String) this.getPropertyValue("emergency_contact");

        List<String> contacts = new ArrayList<>();
        String [] numbers = result.split(",");
        for (String number : numbers)
        {
            contacts.add(number);
        }
        return contacts;
    }

    /**
     * 设置亲情联系人
     * @param numbers   亲情联系人列表
     * @throws IotServerException
     * @throws IotClientException
     */
    public void setFamilyNumbers(List<FamilyNumber> numbers) throws IotServerException, IotClientException {

        JSONArray jsonArray = new JSONArray();
        for (FamilyNumber familyNumber : numbers) {
            jsonArray.add(familyNumber.toJsonObject());
        }
        System.out.println(jsonArray.toString());
        this.setPropertyValue("family_numbers", jsonArray);
    }

    /**
     * 获取亲情联系人
     * @return 亲情联系人列表
     * @throws IotServerException
     * @throws IotClientException
     */
    public List<FamilyNumber> getFamilyNumbers() throws IotServerException, IotClientException{
        List<FamilyNumber> familyNumbers = new ArrayList<>();

        JSONArray result = (JSONArray) this.getPropertyValue("family_numbers");
        for(int i = 0; i < result.size(); i ++) {
           JSONObject jsonObject = result.getJSONObject(i);
           FamilyNumber familyNumber = new  FamilyNumber();
           familyNumber.fromJsonObject(jsonObject);

           familyNumbers.add(familyNumber);
        }

        return familyNumbers;
    }

    /**
     * 设置音量大小
     * @param volume   0 - 100
     * @throws IotServerException
     * @throws IotClientException
     */
    public  void setAudioVolume(int volume) throws IotServerException, IotClientException {
        this.setPropertyValue("volume", volume);
    }

    /**
     * 获取音量大小
     * @return  音量大小
     */
    public int getAudioVolume() throws IotServerException, IotClientException {
      int volume = (int)this.getPropertyValue("volume");
      return volume;
    }

    /**
     * 获取定时任务
     * @return 定时任务列表
     * @throws IotServerException
     * @throws IotClientException
     */
    public List<WeekTimerTask> getWeekTimerTasks() throws IotServerException, IotClientException{
        List<WeekTimerTask> weekTimerTasks = new ArrayList<>();

        JSONArray result = (JSONArray) this.getPropertyValue("timer_tasks");
        for(int i = 0; i < result.size(); i ++) {
            JSONObject jsonObject = result.getJSONObject(i);
            WeekTimerTask timerTask = new  WeekTimerTask();
            timerTask.fromJsonObject(jsonObject);

            weekTimerTasks.add(timerTask);
        }

        return weekTimerTasks;
    }

    /**
     * 设置定时任务
     * @param tasks  定时任务列表
     * @throws IotServerException
     * @throws IotClientException
     */
    public void setWeekTimerTasks(List<WeekTimerTask> tasks) throws IotServerException, IotClientException{
        JSONArray jsonArray = new JSONArray();
        for (WeekTimerTask timerTask : tasks) {
            jsonArray.add(timerTask.toJsonObject());
        }
        System.out.println(jsonArray.toString());
        this.setPropertyValue("timer_tasks", jsonArray);
    }

    /**
     * 获取子设备列表
     * @return  子设备列表
     * @throws IotServerException
     * @throws IotClientException
     */
    public List<SubDevice> getSubDevices() throws IotServerException, IotClientException {
        JSONArray jsonArray = (JSONArray) this.getPropertyValue("subdevices");
        List<SubDevice> subDevices = new ArrayList<>();

        for(int i = 0; i < jsonArray.size() ; i ++) {
            JSONObject jsonObject =  jsonArray.getJSONObject(i);
            SubDevice subDevice = new SubDevice(jsonObject);
            subDevice.fromJsonObject(jsonObject);
            subDevices.add(subDevice);
        }

        return subDevices;
    }

    /**
     * 添加子设备
     * @param subDevice  子设备
     * @throws IotServerException
     * @throws IotClientException
     */
    public  void addSubDevice(SubDevice subDevice) throws IotServerException, IotClientException {
        JSONObject jsonObject = subDevice.toJsonObject();

        this.callService("subdevice_add",  jsonObject.getInnerMap());
    }

    /**
     * 修改子设备
     * @param subDevice  子设备
     * @throws IotServerException
     * @throws IotClientException
     */
    public void changeSubDevice(SubDevice subDevice) throws IotServerException, IotClientException {
        JSONObject jsonObject = subDevice.toJsonObject();
        jsonObject.remove("devtype");
        this.callService("subdevice_change",  jsonObject.getInnerMap());
    }

    /**
     * 删除子设备
     * @param deviceSN  子设备ID
     * @throws IotServerException
     * @throws IotClientException
     */
    public void deleteSubDevice(String deviceSN) throws IotServerException, IotClientException {

        HashMap<String, Object > param = new HashMap<>();
        param.put("uid", deviceSN);

        this.callService("subdevice_del", param);
    }

    /**
     * 开始服务打卡
     * @param seconds  超时时间（秒）
     * @throws IotServerException
     * @throws IotClientException
     */
    public void servicePunchStart(int seconds) throws IotServerException, IotClientException {

        HashMap<String, Object > param = new HashMap<>();
        param.put("timeout", seconds);
        this.callService("service_punch_start", param);
    }

    /**
     * 完成打卡
     * @param code  打卡验证码
     * @return  错误码  0 - 成功   1 未启动打卡  2 超时  3  验证码错误
     */
    public int servicePunchFinish(String code) throws IotServerException, IotClientException {
        HashMap<String, Object > param = new HashMap<>();
        param.put("punch_code", code);
        CallServiceResponse response =  this.callService("service_punch_finish", param);
        int result = (int)response.get("result");
        return result;
    }

    /**
     * Text to Speech 文字转语音播放
     * @param text 要播放的文字
     * @return 异步调用requestId
     * @throws IotServerException
     * @throws IotClientException
     */
    public String ttsPlay(String text) throws IotServerException, IotClientException {
        HashMap<String, Object> param = new HashMap<>();
        param.put("utf8_text", text);

        CallServiceResponse response =  this.callService("tts_play_cmd", param);
        return response.getRequestId();
    }

    /**
     * 语音留言
     * @param mid   留言ID   字符串 长度<16
     * @param url   音频文件url
     * @param format   音频文件格式  0 amr  1 mp3
     * @return  异步调用requestId
     * @throws IotServerException
     * @throws IotClientException
     */
    public String leaveMessageAdd(String mid, String url, int format) throws IotServerException, IotClientException {
        HashMap<String, Object> param = new HashMap<>();
        param.put("mid", mid);
        param.put("url", url);
        param.put("format", format);

        CallServiceResponse response =  this.callService("leave_message_add", param);
        return response.getRequestId();
    }

    /**
     * 自定义设置2个功能键功能
     * @param key1   功能键1功能
     * @param key2   功能键2功能
     */
    public void setFunctionKeys(FunctionKey key1, FunctionKey key2) throws IotServerException, IotClientException {

        JSONArray jsonArray = new JSONArray();
        jsonArray.add(key1.toJsonObject());
        jsonArray.add(key2.toJsonObject());

        this.setPropertyValue("function_keys", jsonArray);
    }



}
